import { ParagraphNode, TextNode } from "./mainNode/index";
import DelimiterStack from "./DelimiterStack";
import StrongNode from "./mainNode/strong_node";
import EmphNode from "./mainNode/emph_node";
export default class MarkdownParseLine {
  static textReg = /^[^\[\]*_~]+/m;
  constructor() {
    this.offset_ = 0;
    this.line_ = "";
    this.delimiter_ = null; // 特殊字符节点树
    this.mnode_ = null; // 主节点树
  }
  init(line) {
    this.offset_ = 0;
    this.line_ = line;
    this.mnode_ = new ParagraphNode();
    this.parseLine_();
    this.transformSpecialCharacters_();
    console.log(this.mnode_);
    return this.mnode_;
  }
  match_(reg) {
    const matched = reg.exec(this.line_.slice(this.offset_));
    if (matched) {
      this.offset_ += matched[0].length;
      return matched[0];
    } else {
      return null;
    }
  }
  parseLine_() {
    let char = "";
    while ((char = this.line_[this.offset_])) {
      switch (char) {
        case "*":
        case "-":
        case "~":
          this.parseSpecialCharacters_(char);
          break;
        default:
          this.parseText_();
      }
    }
  }
  // 将特殊字符转成标签
  parseSpecialCharacters_(char) {
    let count = 0; // 相同字符数量
    let startPos = this.offset_;
    while (char === this.line_[this.offset_]) {
      count++;
      this.offset_++;
    }
    const textNode = new TextNode(
      this.line_.substring(startPos, startPos + count)
      // this.line_.substr(startPos, count)
    );
    this.mnode_.appendChild(textNode);
    const delimiter = new DelimiterStack(char, count, textNode);
    // 拼接成特殊字符链
    if (this.delimiter_) {
      this.delimiter_.next = delimiter;
      delimiter.prev = this.delimiter_;
    }
    this.delimiter_ = delimiter;
  }
  // 将字符转成文字节点存储
  parseText_() {
    const matchText = this.match_(MarkdownParseLine.textReg);
    if (matchText) {
      this.mnode_.appendChild(new TextNode(matchText));
    }
  }
  transformSpecialCharacters_() {
    let closer = this.delimiter_;
    let opener = null;
    while (closer) {
      const char = closer.char_;
      // TODO优化点
      if (char === "*" || char === "_") {
        opener = this.transformSpecialCharactersOpener_(closer);
        if (opener) {
          // 记录消耗的字符数
          let useCount = 0;
          const openerNode = opener.mnode_;
          const closeNode = closer.mnode_;
          let transNode = null;
          if (char === "*" || char === "_") {
            if (opener.currentCount >= 2 && closer.currentCount >= 2) {
              transNode = new StrongNode();
              useCount = 2;
            } else {
              transNode = new EmphNode();
              useCount = 1;
            }
          }
          // 消除字符栈里面使用字符数
          opener.currentCount -= useCount;
          // 消除文本节点上的相应字符数
          openerNode.text = openerNode.text.slice(useCount);
          closer.currentCount -= useCount;
          closeNode.text = closeNode.text.slice(useCount);
          let betweenNode = openerNode.next;
          while (betweenNode && betweenNode !== closeNode) {
            transNode.appendChild(betweenNode);
            betweenNode = betweenNode.next;
          }
          openerNode.insertAfter(transNode);
          console.log(openerNode);
          DelimiterStack.removeBetween(opener, closer);
          // 将无效的字符区间进行处理
          if (opener.currentCount === 0) {
            opener.remove();
            openerNode.unlink();
          }
          if (closer.currentCount === 0) {
            const nextClose = closer.next;
            if (this.delimiter_ === closer) {
              this.delimiter_ = closer.prev;
            }
            closer.remove();
            closer = nextClose;
            closeNode.unlink();
          }
        } else {
          // 无法作为闭合区间，将标识往后一个字符移动
          closer = closer.next;
        }
      } else {
        closer = closer.next;
      }
    }
  }
  // 查找前面相同符号是否有闭合的opener
  transformSpecialCharactersOpener_(closer) {
    let opener = closer.prev;
    while (opener && opener !== null) {
      if (opener.char === closer.char) {
        return opener;
      } else {
        opener = opener.prev;
      }
    }
  }
}
